#include <stdio.h>
#include <set>
#include <mutex>
#include "net/event_loop_thread.h"
#include "net/event_loop_thread_pool.h"
#include "net/tcp_client.h"

static rr::nio::EventLoopThread::Sptr loop_thread;

static rr::nio::TcpClient::Sptr tcp_client;

static const std::string kTestSendMsg = "hello world";

static void TestCloseCallback(rr::nio::TcpConnectionVar conn)
{
    printf("TestCloseCallback: conn[%p]\n", conn.get());
}

static void TestConnectionCallback(rr::nio::TcpConnectionVar conn)
{
    printf("TestConnectionCallback: conn[%p]\n", conn.get());
}

static void TestMessageCallback(rr::nio::TcpConnectionVar conn, rr::nio::Buffer *buf)
{
    std::string data(buf->Peek(), buf->ReadableBytes());
    printf("TestConnectionCallback: conn[%p] msg[%s]\n", conn.get(), data.c_str());

    if(std::string::npos != data.find("end")) {
        buf->RetrieveAll();
    }
}

static void TestMessageSendCallback(rr::nio::WriteInfo& info)
{
    printf("TestMessageSendCallback: status:%d msg[%.*s] msg addr[%p] user_data:%p\n", info.status, info.size, info.buf, info.buf, info.user_data);
}

void TestTcpClinetStart()
{
    printf("TestTcpClinetStart begin\n");
    if(!loop_thread) {
        loop_thread = std::make_shared<rr::nio::EventLoopThread>();
        loop_thread->StartLoop();
    }

    auto loop = loop_thread->GetLoop();
    loop->RunInLoop([loop]() {
        rr::nio::InetAddress addr("10.10.30.173", 8080);
        tcp_client = std::make_shared<rr::nio::TcpClient>(loop.get());
        tcp_client->SetConnectionCallback(TestConnectionCallback);
        tcp_client->SetConCloseCallback(TestCloseCallback);
        tcp_client->SetMessageCallback(TestMessageCallback);
        tcp_client->Start(addr);
    });

    printf("TestTcpClinetStart end\n");

}

void TestTcpClinetStop()
{
    printf("TestTcpClinetStop begin\n");

    if(!loop_thread) {
        printf("TestTcpClinetStop error\n");
        return;
    }

    auto loop = loop_thread->GetLoop();
    loop->RunInLoop([loop]() {
        if(tcp_client) {
            tcp_client->Close([]() {
                printf("TestTcpClinetStop tcp_client->Close cb:\n");
                tcp_client.reset();
            });
        }
    });

    do
    {
        printf("TestEventLoopThreadStop begin\n");
        loop_thread->StopLoop();
        printf("TestEventLoopThreadStop end\n");
        loop_thread.reset();
    } while (0);

    printf("TestTcpClinetStop end\n");

}

void TestTcpClinetSend()
{
    if(!loop_thread || !tcp_client) {
        printf("TestTcpClinetSend error\n");
        return;
    }

    static int32_t isend_count = 1;
    loop_thread->GetLoop()->RunInLoop([]() {
        if(tcp_client && tcp_client->GetCoon()) {
            rr::nio::Buffer::Sptr buf = std::make_shared<rr::nio::Buffer>(1024);
            buf->Append(kTestSendMsg.c_str(), kTestSendMsg.size());
            printf("Send buf:%p size:%zu\n", buf->Peek(), buf->ReadableBytes());
            
            auto send_func = [buf](rr::nio::WriteInfo& info) {
                printf("send_func: status:%d msg[%.*s] msg addr[%p] user_data:%ld\n", info.status, info.size, info.buf, info.buf, (intptr_t)info.user_data);
            };

            tcp_client->GetCoon()->Send(buf, send_func, (void *)(intptr_t)(isend_count++));
            tcp_client->GetCoon()->SendNoCopy(kTestSendMsg.c_str(), kTestSendMsg.size(), TestMessageSendCallback, (void *)(intptr_t)(isend_count++));
        }
    });
}